home *** CD-ROM | disk | FTP | other *** search
/ Extra! Mainframe / Extra! Mainframe for Windows 95.iso / snaserv / source / snacmain.c < prev    next >
Encoding:
C/C++ Source or Header  |  1995-10-01  |  22.0 KB  |  905 lines

  1. /***************************************************************************
  2. **
  3. **    File:            SNACMAIN.C
  4. **    Purpose:        DLL main routine
  5. **    Notes:
  6. **
  7. ****************************************************************************/
  8.  
  9. #define SNACMAIN_C
  10.  
  11. #include "stdinc.h"
  12. #include "setupapi.h"
  13. #include "cui.h"
  14. #include "snacdlgs.h"
  15. #include "stdtypes.h"
  16. #include "datadef.h"
  17.  
  18. BOOL WINAPI DllMain ( HANDLE hModule, DWORD dwReason, LPVOID lpReserved );
  19.  
  20. BOOL __export __loadds CALLBACK FBillbrdDlgProc ( HWND hdlg, UINT uiMsg,
  21.                                             WPARAM wParam, LPARAM lParam );
  22. LRESULT CALLBACK BBmpProc ( HWND hwnd, UINT uiMsg,
  23.                                             WPARAM wParam, LPARAM lParam );
  24.  
  25. /* Private Functions
  26. */
  27. static VOID    FAR PASCAL PaintBorder ( HWND hwnd );
  28. static HFONT   FAR PASCAL HfontSetBBFont ( HWND hdlg );
  29. static int     FAR PASCAL DyScaleToScreen ( HDC hdc, int dy );
  30. static HBITMAP FAR PASCAL LoadBitmapItem ( HANDLE hInst, LPSTR lpName,
  31.                             BOOL * pfDefault );
  32. static LONG    FAR PASCAL DrawDlgBmpItem(HWND, HDC, LPSTR, DWORD, int, int, int, int);
  33. static BOOL    FAR PASCAL FRegisterWinClasses ( VOID );
  34. static BOOL    FAR PASCAL FUnregisterWinClasses ( VOID );
  35.  
  36. /* System Color Macros
  37. */
  38. #define NearestColor(hdc,rgb) (GetNearestColor(hdc,rgb) & 0x00FFFFFFL)
  39. #define EraseRect(hwnd,hdc,prc) ExtTextOut(hdc,0,0,ETO_OPAQUE,prc,NULL,0,NULL)
  40.  
  41. /* Global Data
  42. */
  43. static HINSTANCE hinstSamp = NULL;
  44.  
  45. static char *rgszPostman[] = { "postwm", "postbm", "postaf", "postwf" };
  46. #define cszPostman    4
  47.  
  48. /* Full path to the font resource file we create. */
  49. char szFor[cchSzMax];
  50. char szTtf[cchSzMax];
  51. int fFontReady = fFalse;
  52. int fInitFont = fFalse;
  53. HBRUSH hbrBillboard = NULL;
  54.  
  55. /* REVIEW: Need to see if the new code in DllMain using this guy is ok */
  56. int fSetupFont = fFalse;
  57.  
  58. /* Names of the font files for the billboard headline */
  59. #define szSetupTtfFile    "wwsetup.ttf"        
  60. #define szSetupForFile    "wwsetup.for"
  61.  
  62.  
  63. /*
  64. **    Purpose:
  65. **        Initialization routine for DLL.
  66. **    Arguments:
  67. **    Returns:
  68. **        1 always
  69. **
  70. ***************************************************************************/
  71. BOOL WINAPI DllMain ( HANDLE hModule, DWORD dwReason, LPVOID lpReserved )
  72. {
  73.  
  74. #ifdef NEVER    /* REVIEW */
  75.     int  cch;
  76. #endif
  77.  
  78.     Unused(lpReserved);
  79.  
  80.     /* REVIEW: Need to see if this code in DllMain is ok since it is
  81.      *    different from the stuff we have in LibMain (16-bit).
  82.      */
  83.     switch( dwReason) {
  84.     case DLL_PROCESS_ATTACH:
  85.  
  86.         Assert(hinstSamp == NULL);
  87.         hinstSamp = hModule;
  88.  
  89.         if (!FRegisterWinClasses())
  90.             return (0);
  91.  
  92.         szFor[0] = '\0';
  93.         szTtf[0] = '\0';
  94.  
  95. #ifdef NEVER    /* REVIEW */
  96.         /* 
  97.          * Locate the font file in the directory in which the DLL is found, 
  98.          * create a resource in the same directory and then add the font 
  99.          */
  100.         if ((cch = GetModuleFileName(hModule, szTtf, 256)) != 0)
  101.             {
  102.             char * pch;
  103.         
  104.             /* Strip off the file name part.  Leave the backslash */
  105.             for (pch = szTtf + cch; *pch != '\\'; pch--)
  106.                 ;
  107.             *++pch = '\0';
  108.  
  109.             /* Build the file names */
  110.             lstrcat(szTtf, szSetupTtfFile);
  111.             GetWindowsDirPath(szFor, 256);
  112.             lstrcat(szFor, szSetupForFile);
  113.  
  114.             RemoveFile(szFor, cmoForce);
  115.              fSetupFont = CreateScalableFontResource(1, szFor, szTtf, NULL);
  116.             }
  117. #endif /* NEVER */
  118.         break;
  119.  
  120.     case DLL_PROCESS_DETACH:
  121.         {
  122.  
  123.         /* Clean up our messes... */
  124.         if (szFor[0] != '\0')
  125.             RemoveFile(szFor, cmoForce);
  126.  
  127.         if (szTtf[0] != '\0')
  128.             RemoveFile(szTtf, cmoForce);
  129.  
  130.         if (!FUnregisterWinClasses())
  131.             return (0);
  132.  
  133.         break;
  134.         }
  135.     }
  136.  
  137.     return TRUE;
  138. }
  139.  
  140.  
  141. /*
  142. **    Purpose:
  143. **        Function that must be implemented and exported from every
  144. **        billboard/custom action .DLL called by Acme.  Used to validate
  145. **        that the .DLL was built with the correct version of the Acme
  146. **        header files.
  147. **    Arguments:
  148. **        none.
  149. **    Returns:
  150. **        Header files version string from datadef.h.
  151. **    Notes:
  152. **        Function prototype defined in datadef.h.
  153. **
  154. ****************************************************************************/
  155. SZ WINAPI SzGetDatadefVer ( VOID )
  156. {
  157.     return (SZ_DATADEF_VER);
  158. }
  159.  
  160.  
  161. /*
  162. **    Purpose:
  163. **        Billboard dialog proc.
  164. **    Arguments:
  165. **        Standard windows args.
  166. **    Returns:
  167. **        fTrue if message handled, fFalse otherwise.
  168. **    Notes:
  169. **
  170. ****************************************************************************/
  171. BOOL __export __loadds CALLBACK FBillbrdDlgProc ( HWND hdlg, UINT uiMsg,
  172.                                             WPARAM wParam, LPARAM lParam )
  173. {
  174.     /* WARNING: Using static hfont here assumes no two bb dialogs
  175.     *    will be using this proc at the same time!
  176.     */
  177.     static HFONT hfont = (HFONT)NULL;
  178.  
  179.     Unused(wParam);
  180.     Unused(lParam);
  181.  
  182.     switch (uiMsg)
  183.         {
  184.         case WM_PAINT:
  185.             PaintBorder(hdlg);
  186.             return (fFalse);
  187.  
  188.         case WM_INITDIALOG:
  189.             Assert(hfont == (HFONT)NULL);    /* Only one bb at a time. */
  190.             hfont = HfontSetBBFont(hdlg);
  191.             ReactivateSetupScript();
  192.             return (fTrue);
  193.  
  194.         case STF_REINITDIALOG:
  195.         case STF_ACTIVATEAPP:
  196.             return (fTrue);
  197.  
  198.         case WM_CLOSE:
  199.         case WM_COMMAND:
  200.             Assert(fFalse);
  201.             break;
  202.  
  203.         case WM_DESTROY:
  204.             if (hfont != (HFONT)NULL)
  205.                 {
  206.                 DeleteObject(hfont);
  207.                 hfont = (HFONT)NULL;
  208.                 }
  209.             break;
  210.         }
  211.  
  212.     return (fFalse);
  213. }
  214.  
  215.  
  216. /*  E R A S E  R E C T  C O L */
  217. /*-------------------------------------------------------------------------
  218.     %%Function: EraseRectCol
  219.     %%Contact: PhillipG
  220.     %%Reviewed:
  221.  
  222.     Erase prect, with col as the background color.    
  223. -------------------------------------------------------------------------*/
  224. void EraseRectCol(HDC hdc, RECT *prect, COLORREF col)
  225. {
  226.     SetBkColor(hdc, col);
  227.     ExtTextOut(hdc, 0, 0, ETO_OPAQUE, prect, (LPSTR)NULL, 0, NULL);
  228. }
  229.  
  230.  
  231. #define dxBrdr    7
  232. #define colBorderLeft      RGB(  0,128,128)
  233. #define colBorderTop       RGB(128,  0,128)
  234. #define colBorderShadow    RGB(128,128,128)
  235. #define colHeadlineLine    RGB(  0,128,128)
  236.  
  237. /*
  238. **    Purpose:
  239. **    Arguments:
  240. **    Returns:
  241. **    Notes:
  242. **    
  243. ****************************************************************************/
  244. static VOID FAR PASCAL PaintBorder(HWND hwnd)
  245. {
  246.     PAINTSTRUCT    ps;
  247.     RECT rect;
  248.     HDC     hdc;
  249.     int iBdr;
  250.     int xpLeft;
  251.     int xpRight;
  252.     int ypTop;
  253.     int ypBottom;
  254.     
  255.     GetClientRect(hwnd, &rect);
  256.     xpLeft = rect.left;
  257.     xpRight = rect.right;
  258.     ypTop = rect.top;
  259.     ypBottom = rect.bottom;
  260.     if ((hdc = BeginPaint(hwnd, &ps)) != NULL)
  261.         {
  262.         /* draw dxBrdr lines */
  263.         for (iBdr = 0; iBdr < dxBrdr; iBdr++)
  264.             {
  265.             /* draw the top line */
  266.             rect.top = ypTop;
  267.             rect.left = xpLeft + 1;
  268.             rect.bottom = ypTop + 1;
  269.             rect.right = xpRight;
  270.             EraseRectCol(hdc, &rect, colBorderTop);
  271.  
  272.             /* Draw the left line */
  273.             rect.top = ypTop;
  274.             rect.left = xpLeft;
  275.             rect.bottom = ypBottom;
  276.             rect.right = xpLeft + 1;
  277.             EraseRectCol(hdc, &rect, colBorderLeft);
  278.             
  279.             /* Draw the bottom line */
  280.             rect.top = ypBottom - 1;
  281.             rect.left = xpLeft;
  282.             rect.bottom = ypBottom;
  283.             rect.right = xpRight;
  284.             EraseRectCol(hdc, &rect, colBorderShadow);
  285.             
  286.             /* Draw the right line */
  287.             rect.top = ypTop + 1;
  288.             rect.left = xpRight - 1;
  289.             rect.bottom = ypBottom;
  290.             rect.right = xpRight;
  291.             EraseRectCol(hdc, &rect, colBorderShadow);
  292.  
  293.             /* Move all sides in one pixel. */
  294.             xpLeft++;
  295.             xpRight--;
  296.             ypTop++;
  297.             ypBottom--;
  298.             }
  299.         }
  300.     EndPaint(hwnd, (LPPAINTSTRUCT)&ps);
  301. }
  302.  
  303.  
  304. /*
  305. **    Purpose:
  306. **    Arguments:
  307. **    Returns:
  308. **    Notes:
  309. **
  310. ****************************************************************************/
  311. static HFONT FAR PASCAL HfontSetBBFont ( HWND hdlg )
  312. {
  313.     HFONT   hDlgFont;
  314.     LOGFONT lFont;
  315.     int     idc;
  316.  
  317.     if ((hDlgFont = (HFONT)SendMessage(hdlg, WM_GETFONT, 0, 0L)) != hfontNull)
  318.         {
  319.         if (GetObject(hDlgFont, sizeof(LOGFONT), (LPSTR)&lFont))
  320.             {
  321.             lFont.lfWeight = FW_NORMAL;
  322.             if ((hDlgFont = CreateFontIndirect((LPLOGFONT)&lFont)) != NULL)
  323.                 {
  324.                 for (idc = IDC_BBTEXT1; GetDlgItem(hdlg,idc) != (HWND)NULL;
  325.                       ++idc)
  326.                     {
  327.                     SendDlgItemMessage(hdlg, idc, WM_SETFONT,
  328.                             (WPARAM)hDlgFont, 0L);
  329.                     }
  330.                 }
  331.             }
  332.         }
  333.     return (hDlgFont);
  334. }
  335.  
  336.  
  337. #define cbResNameMax  255
  338. /*
  339. **    Purpose:
  340. **        Billboard bitmap window proc.
  341. **    Arguments:
  342. **    Returns:
  343. **    Notes:
  344. **
  345. ****************************************************************************/
  346. LRESULT CALLBACK BBmpProc ( HWND hwnd, UINT uiMsg,
  347.                                             WPARAM wParam, LPARAM lParam )
  348. {
  349.     static int iszPostman;    /* WARNING: Restricted to one instance */
  350.     PAINTSTRUCT ps;
  351.     TEXTMETRIC    tm;
  352.     HDC   hdc;
  353.     int      DX, DY;
  354.     char  rgchBmp[cbResNameMax];
  355.  
  356.     switch (uiMsg)
  357.         {
  358.         case WM_CREATE:
  359.             iszPostman = (int)(LOWORD(GetTickCount()) % cszPostman);
  360.             break;
  361.  
  362.         case WM_PAINT:
  363.             GetWindowText(hwnd, rgchBmp, cbResNameMax);
  364.             if (lstrcmp(rgchBmp, "postman") == 0)
  365.                 {
  366.                 Assert(iszPostman >= 0 && iszPostman < cszPostman);
  367.                 Assert(lstrlen(rgszPostman[iszPostman]) < sizeof rgchBmp);
  368.                 lstrcpy(rgchBmp, rgszPostman[iszPostman]);
  369.                 }
  370.             /* 
  371.              * REVIEW: NYI: If ctl3d.dll is not active for some
  372.              *    reason (such as if video is EGA) we should use
  373.              *    default window color instead.
  374.              */
  375.             if ((hdc = BeginPaint(hwnd, &ps)) != NULL)
  376.                 {
  377. #ifdef NOTUSED    /* REVIEW */
  378.                 COLORREF col;
  379.                 
  380.                 if (GetSystemMetrics(SM_CYSCREEN) < 450) /* EGA */
  381.                     col = GetSysColor(COLOR_WINDOW);
  382.                 else
  383.                     col = GetSysColor(COLOR_BTNFACE);
  384.                 EraseRectCol(hdc, &ps.rcPaint, NearestColor(hdc, col));
  385. #endif /* NOTUSED */
  386.                 GetTextMetrics(hdc, &tm);
  387.                 DX = DY = (tm.tmHeight) / 4;
  388.                 DrawDlgBmpItem(hwnd, hdc, rgchBmp, SRCCOPY, fFalse, fFalse, DX, DY);
  389.                 }
  390.             EndPaint(hwnd, (LPPAINTSTRUCT)&ps);
  391.             return (0L);
  392.         }
  393.     return (DefWindowProc(hwnd, uiMsg, wParam, lParam));
  394. }
  395.  
  396.  
  397. /*
  398. **    Purpose:
  399. **    Arguments:
  400. **    Returns:
  401. **    Notes:
  402. **
  403. ****************************************************************************/
  404. static int FAR PASCAL DyScaleToScreen ( HDC hdc, int dy )
  405. {
  406.     int dyNew;
  407.  
  408.     switch (GetDeviceCaps(hdc, LOGPIXELSY))
  409.         {
  410.         case 72:    /* EGA */
  411.             dyNew = (int) (((LONG) dy) * 350L / 480L);
  412.             break;
  413.         case 96:    /* VGA */
  414.         case 120:    /* XGA (8514) */
  415.         default:
  416.             dyNew = dy;
  417.             break;
  418.         }
  419.     return (dyNew);
  420. }
  421.  
  422.  
  423. /*
  424. **    Purpose:
  425. **        Load a device specific bitmap from a resource file.
  426. **    Arguments:
  427. **    Returns:
  428. **    Notes:
  429. **
  430. ****************************************************************************/
  431. static HBITMAP FAR PASCAL LoadBitmapItem ( HANDLE hInst, LPSTR lpName,
  432.                                             BOOL * pfDefault )
  433. {
  434.     char    szName[80];
  435.     HBITMAP    hbm;
  436.     int        nColors;
  437.     int        dxScreen;
  438.     int        dyScreen;
  439.     HDC        hdc;
  440.     BOOL    fDef = fFalse;
  441.  
  442.     hdc = GetDC(NULL);
  443.  
  444.     nColors  = GetDeviceCaps(hdc, NUMCOLORS);
  445.     dxScreen = GetSystemMetrics(SM_CXSCREEN);
  446.     dyScreen = GetSystemMetrics(SM_CYSCREEN);
  447.     if (dyScreen < 479) /* double scan CGA is 400 */
  448.         dyScreen = 350;
  449.  
  450.     ReleaseDC(NULL, hdc);
  451.  
  452.     /* Look for a resource of the form WxHxC.
  453.     */
  454.     wsprintf(szName, "%s%dx%dx%d", lpName, dxScreen, dyScreen, nColors);
  455.     hbm = LoadBitmap(hInst, szName);
  456.  
  457.     /* Look for a resource of the form WxH.
  458.     */
  459.     if (!hbm)
  460.         {
  461.         wsprintf(szName, "%s%dx%d", lpName, dxScreen, dyScreen);
  462.         hbm = LoadBitmap(hInst, szName);
  463.         }
  464.  
  465.     /* Look for the default resource name.
  466.     */
  467.     if (!hbm)
  468.         {
  469.         hbm = LoadBitmap(hInst, lpName);
  470.         fDef = fTrue;
  471.         }
  472.  
  473.     *pfDefault = fDef;
  474.     return (hbm);
  475. }
  476.  
  477.  
  478. #define DPSoa    0x00A803A9L
  479. #define DPa      0x00A000C9L
  480. /*
  481. **    Purpose:
  482. **    Arguments:
  483. **    Returns:
  484. **    Notes:
  485. **
  486. ****************************************************************************/
  487. static LONG FAR PASCAL DrawDlgBmpItem(HWND hwnd, HDC hdc, LPSTR szBmp, 
  488.         DWORD rop, int fShadow, int fCalcSizeOnly, int DX, int DY)
  489. {
  490.     HDC        hdcMem;
  491.     HBITMAP    hbmpSav;
  492.     HBITMAP    hbmp;
  493.     BITMAP    bmp;
  494.     int        bmH;
  495.     int     xw;
  496.     int     yw;
  497.     BOOL    fScale;
  498.     RECT rect;
  499.  
  500.     if ((hbmp = LoadBitmapItem(hinstSamp, szBmp, &fScale)) == NULL)
  501.         return (0L);
  502.  
  503.     GetObject(hbmp, sizeof(BITMAP), (LPSTR)&bmp);
  504.  
  505.     if (fScale)
  506.         bmH = DyScaleToScreen(hdc, bmp.bmHeight);
  507.     else
  508.         bmH = bmp.bmHeight;
  509.  
  510.     if (fCalcSizeOnly)
  511.         {
  512.         DeleteObject(hbmp);
  513.         return (MAKELONG(bmp.bmWidth + 4, bmH + 4));
  514.         }
  515.  
  516.     hdcMem = CreateCompatibleDC(hdc);
  517.     hbmpSav = SelectObject(hdcMem, hbmp);
  518.  
  519.     SelectObject(hdc, GetStockObject(BLACK_BRUSH));
  520.     if (fShadow)
  521.         {
  522.         /*
  523.          * WARNING! This code is broken.  This clock still draws the 
  524.          * shadow based on the top left corner, whereas the StretchBlt
  525.          * below draws the bitmap in the lower right corner.
  526.          */
  527.         
  528.         xw = DX + 2;
  529.         yw = DY + 2;
  530.         
  531.         SelectObject(hdc, GetStockObject(GRAY_BRUSH));
  532.         PatBlt(hdc, xw - 3, yw - 3, bmp.bmWidth + 4, bmH + 4, PATCOPY);
  533.         rect.left = xw - DX;
  534.         rect.right = rect.left + bmp.bmWidth;
  535.         rect.top = yw - DY;
  536.         rect.bottom = rect.top + bmH;
  537.         InflateRect(&rect, 2, 2);
  538.         SelectObject(hdc, GetStockObject(WHITE_BRUSH));
  539.         PatBlt(hdc, rect.left, rect.top, rect.right - rect.left,
  540.                         rect.bottom - rect.top, PATCOPY);
  541.         FrameRect(hdc, &rect, GetStockObject(BLACK_BRUSH));
  542.         xw -= DX;
  543.         yw -= DY;
  544.         }
  545.     else
  546.         {
  547.         xw = 0;
  548.         yw = 0;
  549.         }
  550.  
  551.     /* This draws the bitmap in the lower right corner of the control */
  552.     GetClientRect(hwnd, &rect);
  553.  
  554.     StretchBlt(hdc, rect.right - bmp.bmWidth - xw, rect.bottom - bmH - yw, 
  555.                bmp.bmWidth, bmH, hdcMem, 0, 0, bmp.bmWidth, bmp.bmHeight, rop);
  556.  
  557.     SelectObject(hdcMem, hbmpSav);
  558.     DeleteDC(hdcMem);
  559.  
  560.     DeleteObject(hbmp);
  561.     return (MAKELONG(bmp.bmWidth + 4, bmH + 4));
  562. }
  563.  
  564.  
  565. /*  W N D  P R O C  B I L L B O A R D  H E A D L I N E */
  566. /*-------------------------------------------------------------------------
  567.     %%Function: WndProcBillboardHeadline
  568.     %%Contact: PhillipG
  569.     %%Reviewed:
  570.  
  571.     Draw text according to the point size, font and text embedded in 
  572.     the window text for this control.
  573. -------------------------------------------------------------------------*/
  574. long FAR PASCAL WndProcBillboardHeadline(HWND hwnd, WORD message, WORD wParam, 
  575.         LONG lParam)
  576. {
  577.     HDC hdc;
  578.     PAINTSTRUCT ps;
  579.     RECT rect;
  580.     SIZE sSize;
  581.     
  582.     switch (message)
  583.         {
  584.     case WM_SETFONT:
  585.         /* Don't want anyone messing with our fonts! */
  586.         return 1;
  587.  
  588.     case WM_CREATE:
  589.         /* 
  590.          * The first time only, we need to initialize the headline font.  
  591.          * We do this by copying the .TTF file to the Windows directory,
  592.          * creating the destination file name and then calling 
  593.          * CreateScalableFontResource.  Set the global fFontReady if this
  594.          * succeeds.
  595.          */
  596.         if (!fInitFont)
  597.             {
  598.             int cch;
  599.             int cchWin;
  600.             char szSrcTtf[cchSzMax];
  601.             
  602.             fInitFont = fTrue;
  603.             /* 
  604.              * Locate the TTF file in the DLL directory, and copy it to the
  605.              * Windows directory.  We must do this because the DLL could be
  606.              * on a UNC path, which Windows can't handle for a font resource.
  607.              */
  608.             if ((cch = GetModuleFileName(hinstSamp, (char far *)szSrcTtf, cchSzMax)) != 0 &&
  609.                 (cchWin = GetWindowsDirPath((char far *)szTtf, cchSzMax)) != 0)
  610.                 {
  611.                 char *pch;
  612.                 
  613.                 /* Replace DLL file name with TTF file name */
  614.                 for (pch = szSrcTtf + cch; *pch != '\\'; pch--)
  615.                     ;
  616.                 lstrcpy((char far *)++pch, szSetupTtfFile);
  617.  
  618.                 /*
  619.                  * ACME API GetWindowsDirPath includes the null char when it
  620.                  * returns char count, but GetWindowsDirectory does not.
  621.                  * Decrement cchWin by one to adjust.
  622.                  */
  623.                 cchWin--;
  624.                 if (szTtf[cchWin - 1] != '\\')
  625.                     szTtf[cchWin++] = '\\';
  626.                 lstrcpy((char far *)szTtf + cchWin, szSetupTtfFile);
  627.  
  628.                 /* Delete any existing TTF file */
  629.  
  630.                 RemoveFile(szTtf, cmoForce);
  631.                 CopyFile(szSrcTtf, szTtf, cmoOverwrite, 0);
  632.                 
  633.                 if (DoesFileExist(szTtf, femExists))
  634.                     {
  635.                     lstrcpy(szFor, szTtf);
  636.                     lstrcpy((char far *)szFor + cchWin, szSetupForFile);
  637.                     
  638.                     RemoveFile(szFor, cmoForce);
  639.                     fFontReady = CreateScalableFontResource(0,(char far *)szFor, 
  640.                                               (char far *)szTtf, NULL);
  641.                     }
  642.                 }
  643.             }
  644.         break;
  645.     
  646.     case WM_PAINT:
  647.         if ((hdc = BeginPaint(hwnd, &ps)) != NULL)
  648.             {
  649.             COLORREF col;                
  650.             LOGFONT lf;
  651.             HFONT hfont = NULL;
  652.             HFONT hfontOld = NULL;
  653.             RECT rectUL;
  654.             POINT pt;
  655.             int wPt;
  656.             int cch;
  657.             int dxp;
  658.             int fRemFont;
  659.             int dyp;
  660.             char sz[256];
  661.             DWORD dw = 0;
  662.             TEXTMETRIC tm;
  663.             char far *lpchEnd = sz + 256;
  664.             char far *lpchFont;
  665.             char far *lpch;
  666.             
  667.             /*
  668.              * The window text is divided into three parts, separated by
  669.              * tab characters.  
  670.              *
  671.              * The first part is the font size.  (TAB) 
  672.              * The second part is the font name. (TAB)
  673.              * The third part is the headline text.
  674.              */
  675.             GetWindowText(hwnd, sz, 256);
  676.  
  677.             /* init all logfont fields to 0s */
  678.             for (lpch = (char *) &lf; lpch < (char *) &lf + sizeof(LOGFONT); lpch++)
  679.                 *lpch = 0;
  680.  
  681.             /* 
  682.              * The font size is the sum of the digit characters up to 
  683.              * the first tab.
  684.              */
  685.             for (lpch = sz, wPt = 0; *lpch != '\t' && lpch < lpchEnd; lpch++)
  686.                 {
  687.                 char ch;
  688.                 
  689.                 wPt *= 10;
  690.                 if ((ch = *lpch) >= '0' && ch <= '9')
  691.                     wPt += *lpch - '0';
  692.                 }
  693.  
  694.             /* For overflow, set point size to something safe, like 10 */
  695.             if (lpch >= lpchEnd)
  696.                 wPt = 10;
  697.             
  698.             /* Beginning of the font name is after the size and a tab */
  699.             for (lpchFont = ++lpch; *lpch != '\t' && lpch < lpchEnd; lpch++)
  700.                 ;
  701.  
  702.             /* 
  703.              * lpch should now be pointing to the tab between the font name
  704.              * and the control text.  End off the font name string, point to
  705.              * beginning of text.
  706.              */
  707.             *lpch++ = '\0';
  708.             
  709.             /* If overflow, make the font and text null strings */
  710.             if (lpch >= lpchEnd)
  711.                 *lpch = *lpchFont = '\0';
  712.             cch = lstrlen(lpch);
  713.  
  714.             GetClientRect(hwnd, &rect);
  715.             if (GetSystemMetrics(SM_CYSCREEN) < 450) /* EGA */
  716.                 col = GetSysColor(COLOR_WINDOW);
  717.             else
  718.                 col = GetSysColor(COLOR_BTNFACE);
  719.  
  720.             /* Use Arial as a fallback if the custom font isn't available */
  721.             if ((fRemFont = (fFontReady && AddFontResource((char far *)szFor))) == fTrue)
  722.                 lstrcpy(lf.lfFaceName, lpchFont);
  723.             else
  724.                 lstrcpy(lf.lfFaceName, "Arial");
  725.             
  726.             dxp = rect.right - rect.left;
  727.             dyp = rect.bottom - rect.top;
  728.             
  729.             /* 
  730.              * Loop until the text will fit in the control.  Decrease the 
  731.              * size by two points per iteration until it fits.
  732.              */
  733.             dw = (DWORD) -1;
  734.             do 
  735.                 {
  736.                 /* Set the size and get the font. */
  737.                 lf.lfHeight = - MulDiv(wPt, GetDeviceCaps(hdc, LOGPIXELSY), 72);
  738.  
  739.                 if (hfont != NULL)
  740.                     {
  741.                     Assert(hfontOld != NULL);
  742.                     SelectObject(hdc, hfontOld);
  743.                     DeleteObject(hfont);
  744.                     }
  745.                 
  746.                 if ((hfont = CreateFontIndirect(&lf)) != NULL)
  747.                     {
  748.                     /* Only remember the original font. */
  749.                     if (hfontOld == NULL)
  750.                         hfontOld = SelectObject(hdc, hfont);
  751.                     else
  752.                         SelectObject(hdc, hfont);
  753.                     }
  754.  
  755.                 GetTextMetrics(hdc, &tm);
  756.  
  757.                 /* 
  758.                  * We always want to do this once, but unless the horiz
  759.                  * size is too big, don't bother doing it again because
  760.                  * the call is too expensive. 
  761.                  */
  762.                 if (LOWORD(dw) > (unsigned)dxp)
  763.                     GetTextExtentPoint(hdc, lpch, cch, &sSize);
  764.                 wPt -= 2;
  765.                 } 
  766.             while (hfont != NULL && wPt > 0 &&
  767.                     ((int)sSize.cx > dxp || tm.tmHeight > dyp));
  768.                 
  769.             /* 
  770.              * Draw a 3-pixel line under the text of the headline.
  771.              * size of line is 1/2 dlg width or length of text 
  772.              */
  773.             GetWindowRect(GetParent(hwnd), &rectUL);
  774.             pt.x = rectUL.left + ((rectUL.right - rectUL.left) / 2);
  775.             pt.y = 0;
  776.             ScreenToClient(hwnd, &pt);
  777.             
  778.             rectUL.top = rect.bottom - 6;
  779.             rectUL.bottom = rectUL.top + 3;
  780.             rectUL.left = rect.left;
  781.             rectUL.right = max(pt.x, (int)sSize.cx);
  782.             EraseRectCol(hdc, &rectUL, NearestColor(hdc, colHeadlineLine));
  783.  
  784.             SetBkColor(hdc, col);
  785.             SetBkMode(hdc, TRANSPARENT);
  786.             DrawText(hdc, lpch, lstrlen(lpch), &rect, DT_BOTTOM | DT_LEFT | DT_SINGLELINE);
  787.  
  788.             /* Clean up the font objects */
  789.             if (hfontOld != NULL)
  790.                 SelectObject(hdc, hfontOld);
  791.             if (hfont != NULL)
  792.                 {
  793.                 Assert(hfontOld != NULL);
  794.                 DeleteObject(hfont);
  795.                 }
  796.             if (fRemFont)
  797.                 RemoveFontResource((char far *)szFor);
  798.             
  799.             EndPaint(hwnd, &ps);
  800.             return 0;
  801.             }
  802.         break;
  803.         }     /* switch */
  804.     return DefWindowProc(hwnd, message, wParam, lParam);
  805. }
  806.  
  807.  
  808. /*
  809. **    Purpose:
  810. **    Arguments:
  811. **    Returns:
  812. **    Notes:
  813. **
  814. ****************************************************************************/
  815. static BOOL FAR PASCAL FRegisterWinClasses(VOID)
  816. {
  817.     WNDCLASS    wndclass;
  818.  
  819.     /* If EGA, use COLOR_WINDOW */
  820.     if (hbrBillboard == NULL && GetSystemMetrics(SM_CYSCREEN) >= 450)
  821.         hbrBillboard = CreateSolidBrush(GetSysColor(COLOR_BTNFACE));
  822.  
  823.     /* BBMP_CLASS
  824.     */
  825.     wndclass.hCursor        = LoadCursor(NULL, IDC_ARROW);
  826.     wndclass.hIcon            = NULL;
  827.     wndclass.lpszMenuName   = NULL;
  828.     wndclass.lpszClassName  = BBMP_CLASS;
  829.     wndclass.hbrBackground  = hbrBillboard != NULL ? hbrBillboard :
  830.                                 (HBRUSH)COLOR_WINDOW;
  831.     wndclass.hInstance      = hinstSamp;
  832.     wndclass.style            = CS_HREDRAW | CS_VREDRAW;
  833.     wndclass.lpfnWndProc    = (WNDPROC)BBmpProc;
  834.     wndclass.cbClsExtra     = 0;
  835.     wndclass.cbWndExtra     = 0;
  836.  
  837.     if (!RegisterClass(&wndclass))
  838.         {
  839.         WNDCLASS wndclassCur;
  840.         DWORD dwErr = GetLastError();
  841.  
  842.         if (!GetClassInfo(hinstSamp, BBMP_CLASS, &wndclassCur))
  843.             return (fFalse);
  844.         }
  845.  
  846.     /* HEADLINE_CLASS
  847.     */
  848.     wndclass.lpszClassName  = HEADLINE_CLASS;
  849.     wndclass.lpfnWndProc    = (WNDPROC)WndProcBillboardHeadline;
  850.  
  851. #ifdef INEFFICIENT    
  852.     /* NOTE: These fields are the same as previous */
  853.     
  854.     wndclass.hCursor        = LoadCursor(NULL, IDC_ARROW);
  855.     wndclass.hIcon           = NULL;
  856.     wndclass.lpszMenuName   = NULL;
  857.     wndclass.hbrBackground  =  
  858.     wndclass.hInstance      = hinstSamp;
  859.     wndclass.style           = CS_HREDRAW | CS_VREDRAW;
  860.     wndclass.cbClsExtra     = 0;
  861.     wndclass.cbWndExtra     = 0;
  862. #endif
  863.  
  864.     if (!RegisterClass(&wndclass))
  865.         {
  866.         WNDCLASS wndclassCur;
  867.         DWORD dwErr = GetLastError();
  868.  
  869.         if (!GetClassInfo(hinstSamp, HEADLINE_CLASS, &wndclassCur))
  870.             return (fFalse);
  871.         }
  872.  
  873.     return (fTrue);
  874. }
  875.  
  876.  
  877. /*
  878. **    Purpose:
  879. **        Under Win95 (Chicago) it is required to unregister classes
  880. **        when the .DLL is unloaded.
  881. **    Arguments:
  882. **    Returns:
  883. **    Notes:
  884. **
  885. ****************************************************************************/
  886. static BOOL FAR PASCAL FUnregisterWinClasses ( VOID )
  887. {
  888.     if (hbrBillboard != NULL)
  889.         DeleteObject(hbrBillboard);
  890.  
  891.     if (!UnregisterClass(BBMP_CLASS, hinstSamp))
  892.         {
  893.         return (fFalse);
  894.         }
  895.  
  896.     if (!UnregisterClass(HEADLINE_CLASS, hinstSamp))
  897.         {
  898.         return (fFalse);
  899.         }
  900.  
  901.     return (fTrue);
  902. }
  903.  
  904.  
  905.